#ifndef SURFACE_UTILS_H_
#define SURFACE_UTILS_H_

#include "point.h"
#include "texture.h"
#include <vector>
#include <iostream>

struct Surface{
	std::vector<float> points;
	std::vector<float> normals;
	std::vector<float> texture;
	std::vector<unsigned int> indices;
	std::vector<unsigned int> groupsSizes;
};

struct Range{
	Range(){}
	virtual~ Range(){}

	virtual void getRange(unsigned char height,std::vector<float>& result)const=0;
};

class SurfaceUtils{
	private:
		static unsigned int revolutionStep;
	public:
		static SurfaceUtils& instance(){
			static SurfaceUtils _instance;
			return _instance;
		}
		static void setRevolutionStep(unsigned int step){
			revolutionStep=step;
		}

		void calculateRevolutionSurface(const Point& center,const Point& axis,const std::vector<Point>& curvePoints,Surface& surface);
		void calculateRevolutionSurfaceIndices(const std::vector<Point>& curvePoints,Surface& surface);

		void calculateTiledSurface(Point normal,Point center,unsigned int rows,unsigned int cols,float colSize,float rowSize,Surface& surface);
		void calculateTiledSurfaceIndices(unsigned int rows,unsigned int cols,Surface& surface);

		// Calcula vertices de textura segun una sola textura( la autogenerada a partir del heightMap )
		void calculateTiledSurfaceHeightMap(Point normal,Point center,unsigned int rows,unsigned int cols,float colSize,float rowSize,const Texture& heightMap,float scaleHeightFactor,float zeroLevel,Surface& surface);
		void calculateTiledSurfaceHeightMapNormals(Surface& surface);
		void calculateTiledSurfaceHeightMapIndices(unsigned int rows,unsigned int cols,Surface& surface);

		void surfaceToObj(const Surface& surface,std::ostream& out,const std::string& mtlName);

		void generateHeightMapTexture(const std::vector<const Texture*>& textures,Texture& result,const Texture& heightMap,const Range& range);
	private:
		void calculateSurfaceIndices(unsigned int count,unsigned int size,Surface& surface);
		// Mapea una sola textura a toda la malla ( cuando se utliza el heigtmap y su textura autogenerada )
		void calculateSurfaceIndices2(unsigned int count,unsigned int size,Surface& surface);
};

#endif /* SURFACE_UTILS_H_ */
